7.04. Ansible
Ansible
Что такое Ansible
Ansible — это инструмент автоматизации, предназначенный для описания, развертывания и управления состоянием вычислительной инфраструктуры с помощью кода. Он позволяет систематизировать процессы настройки серверов, развёртывания приложений, обновления программного обеспечения и оркестрации сложных взаимодействий между компонентами распределённых систем. Основная цель Ansible — превратить рутинные операции администрирования в воспроизводимые, декларативные и версионируемые процедуры.
Ansible работает без установки агентов на управляемые узлы. Вместо этого он использует стандартные протоколы удалённого доступа, такие как SSH для Unix-подобных систем или WinRM для Windows. Это делает его легковесным, безопасным и совместимым с широким спектром окружений — от локальных машин до облачных платформ, включая Amazon Web Services, Microsoft Azure и Google Cloud Platform.
Система автоматизации конфигурации, развертывания и управления инфраструктурой
Современные ИТ-инфраструктуры представляют собой сложные экосистемы, состоящие из десятков, сотен или даже тысяч серверов, сетевых устройств, баз данных, микросервисов и внешних зависимостей. Ручное управление такой средой становится не только трудоёмким, но и подверженным ошибкам. Даже незначительное отклонение в конфигурации одного узла может привести к сбоям в работе всего приложения.
Система автоматизации решает эту проблему, предоставляя единый язык описания желаемого состояния инфраструктуры. Этот подход известен как Infrastructure as Code (IaC) — инфраструктура как код. Вместо того чтобы выполнять команды вручную на каждом сервере, администратор описывает требуемую конфигурацию в виде текстовых файлов. Эти файлы можно хранить в системах контроля версий, проверять на соответствие стандартам, тестировать и применять многократно в разных окружениях — от разработки до продакшена.
Ansible реализует IaC через декларативный стиль: пользователь указывает, что должно быть достигнуто, а не как это сделать шаг за шагом. Например, вместо написания скрипта, который проверяет наличие пакета, скачивает его, устанавливает зависимости и запускает службу, достаточно объявить: «Пакет nginx должен быть установлен, и служба nginx должна быть запущена и включена при загрузке». Ansible сам определит текущее состояние системы и выполнит минимальный набор действий для достижения цели.
Цель и архитектура Ansible
Основная цель Ansible — обеспечить простоту, надёжность и масштабируемость в управлении инфраструктурой. Он ориентирован на читаемость, минимизацию зависимостей и быстрое внедрение. Архитектура Ansible построена вокруг нескольких ключевых компонентов:
-
Контрольный узел (Control Node) — это машина, на которой запускается Ansible. Именно с неё отправляются команды и плейбуки к управляемым хостам. Контрольный узел требует установленного Python и самого Ansible, но не нуждается в базе данных, демоне или дополнительных сервисах.
-
Управляемые узлы (Managed Nodes) — это целевые серверы, на которых выполняются задачи. На них не требуется устанавливать специальное ПО, кроме интерпретатора Python (для большинства модулей) и открытого SSH-порта.
-
Модули — это исполняемые единицы, которые выполняют конкретные действия: установка пакетов, управление службами, копирование файлов, работа с облачными API и многое другое. Ansible содержит тысячи встроенных модулей и поддерживает создание собственных.
-
Плейбуки (Playbooks) — это основной способ описания автоматизированных процедур. Они написаны на языке YAML и структурированы как последовательности plays, каждый из которых применяется к определённой группе хостов.
-
Инвентарь (Inventory) — это описание целевых хостов: их IP-адреса, доменные имена, принадлежность к группам, переменные и параметры подключения.
Архитектура Ansible является push-ориентированной: контрольный узел инициирует соединение с управляемыми узлами, передаёт необходимые данные и модули, выполняет задачи и завершает сессию. Такой подход упрощает сетевую настройку и повышает безопасность, так как управляемые узлы не должны инициировать исходящие соединения.
Инвентарь
Инвентарь — это фундамент, на котором строится вся автоматизация в Ansible. Он определяет, с какими машинами будет работать система. Инвентарь может быть представлен в виде простого текстового файла, динамического скрипта или комбинации источников.
Статический инвентарь записывается в формате INI или YAML. Пример в INI-стиле:
[web_servers]
192.168.1.10
192.168.1.11
[db_servers]
192.168.1.20
[production:children]
web_servers
db_servers
В этом примере определены две группы хостов: web_servers и db_servers, а также родительская группа production, которая включает обе. Это позволяет применять одни и те же задачи ко всем серверам в production или только к веб-серверам.
Каждому хосту можно назначить переменные прямо в инвентаре:
[web_servers]
web1 ansible_host=192.168.1.10 ansible_user=deploy
web2 ansible_host=192.168.1.11 ansible_user=deploy
Динамический инвентарь генерируется в реальном времени, например, путём запроса к API облачного провайдера. Ansible предоставляет официальные скрипты для AWS, Azure, GCP и других платформ. Это особенно полезно в средах с постоянно меняющейся инфраструктурой, где серверы создаются и уничтожаются автоматически.
Инвентарь может быть задан явно через флаг -i при запуске команды, либо использоваться по умолчанию из файла /etc/ansible/hosts.
Плейбуки
Плейбук — это сердце Ansible. Это файл в формате YAML, который описывает последовательность действий, применяемых к определённым хостам. Плейбук состоит из одного или нескольких plays. Каждый play определяет:
- Целевые хосты (через параметр
hosts); - Переменные, доступные в рамках play;
- Последовательность задач (
tasks); - Обработчики (
handlers); - Роли (
roles), если используются.
Пример простого плейбука:
---
- name: Настройка веб-сервера
hosts: web_servers
become: yes
tasks:
- name: Установка Nginx
apt:
name: nginx
state: present
- name: Запуск службы Nginx
service:
name: nginx
state: started
enabled: yes
Этот плейбук применяется ко всем хостам из группы web_servers. Он повышает привилегии до root (become: yes), устанавливает пакет nginx и гарантирует, что служба запущена и включена при старте системы.
Плейбуки поддерживают условные конструкции, циклы, обработку ошибок, включение других плейбуков и использование шаблонов. Они легко читаются, даже людьми без технического бэкграунда, что делает их отличным инструментом для документирования процессов развёртывания.
Шаблонизация
Шаблонизация позволяет генерировать конфигурационные файлы динамически, подставляя в них значения переменных, фактов о системе или результаты выполнения других задач. Ansible использует шаблонизатор Jinja2, популярный в экосистеме Python.
Файлы шаблонов имеют расширение .j2 и размещаются в каталоге templates внутри проекта или роли. Например, шаблон nginx.conf.j2 может содержать:
server {
listen {{ nginx_port }};
server_name {{ server_name }};
location / {
root {{ document_root }};
index index.html;
}
}
В плейбуке этот шаблон копируется на целевой сервер с помощью модуля template:
- name: Развертывание конфигурации Nginx
template:
src: nginx.conf.j2
dest: /etc/nginx/sites-available/default
notify: Перезапуск Nginx
Переменные nginx_port, server_name и document_root могут быть определены в инвентаре, в самом плейбуке, в групповых переменных или получены из фактов (например, ansible_default_ipv4.address). Такой подход обеспечивает гибкость: один и тот же шаблон работает в разных окружениях — dev, staging, production — без изменения кода.
Ansible Vault
Чувствительные данные, такие как пароли, токены API, закрытые ключи, не должны храниться в открытом виде в репозиториях. Ansible Vault решает эту проблему, позволяя шифровать отдельные файлы или переменные внутри YAML-документов.
Команда ansible-vault create secret.yml создаёт новый зашифрованный файл. Команда ansible-vault encrypt_string 'my_secret' генерирует зашифрованную строку, которую можно вставить прямо в плейбук:
vars:
db_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
66386439653236336462626566653063336164636135393732353639623561303231306366376135306439
При запуске плейбука с зашифрованными данными требуется указать пароль: либо вручную через --ask-vault-pass, либо через файл с помощью --vault-password-file. Ansible автоматически расшифровывает данные перед выполнением задач.
Vault обеспечивает соответствие требованиям безопасности и позволяет хранить всю конфигурацию в одном месте, не нарушая принципов Infrastructure as Code.
AWX и Red Hat Ansible Automation Platform
AWX — это свободный, открытый веб-интерфейс и REST API для управления Ansible. Он предоставляет графический дашборд для запуска плейбуков, просмотра истории выполнений, управления инвентарями, учётными данными и расписаниями. AWX особенно полезен в командах, где несколько человек участвуют в эксплуатации инфраструктуры.
AWX включает:
- Проекты — привязка к Git-репозиториям с плейбуками;
- Инвентари — управление статическими и динамическими источниками;
- Шаблоны заданий — предопределённые конфигурации запуска;
- Учётные данные — безопасное хранение SSH-ключей, паролей, токенов;
- Расписания — автоматический запуск плейбуков по времени;
- Аудит и логирование — полная история всех операций.
Red Hat Ansible Automation Platform — это коммерческая версия, основанная на AWX, с поддержкой, расширенными функциями безопасности, интеграцией с корпоративными системами и возможностью масштабирования в крупных организациях.
Оба решения превращают Ansible из командной утилиты в полноценную платформу автоматизации, пригодную для enterprise-сред.
Роли
Роли — это механизм структурирования и повторного использования кода в Ansible. Когда проекты растут, плейбуки становятся громоздкими и трудно поддерживаемыми. Роли позволяют разбить логику на модульные, самодостаточные компоненты, каждый из которых отвечает за конкретную функцию: установку веб-сервера, настройку базы данных, развёртывание приложения и так далее.
Стандартная структура роли выглядит так:
roles/
└── webserver/
├── tasks/
│ └── main.yml
├── handlers/
│ └── main.yml
├── templates/
│ └── nginx.conf.j2
├── files/
├── vars/
│ └── main.yml
├── defaults/
│ └── main.yml
└── meta/
└── main.yml
tasks/main.yml— основной список задач, выполняемых ролью.handlers/main.yml— обработчики, вызываемые черезnotify.templates/— шаблоны конфигурационных файлов.files/— статические файлы, копируемые на целевые узлы.vars/main.yml— переменные с высоким приоритетом, специфичные для роли.defaults/main.yml— значения по умолчанию, которые можно переопределить.meta/main.yml— метаданные: зависимости от других ролей, поддерживаемые платформы.
Пример использования роли в плейбуке:
---
- name: Развертывание веб-приложения
hosts: webservers
roles:
- webserver
- common
- monitoring
Каждая роль применяется последовательно ко всем хостам из группы webservers. Это позволяет собирать сложные конфигурации из простых, тестируемых блоков. Роли можно публиковать в Ansible Galaxy — централизованном каталоге сообщества, где тысячи разработчиков делятся готовыми решениями для PostgreSQL, Docker, Kubernetes, Jenkins и многих других технологий.
Обработчики
Обработчики — это особый вид задач, которые выполняются только в ответ на явный сигнал. Они полезны для действий, которые должны происходить после изменения состояния системы, но не при каждом запуске плейбука. Например, перезапуск веб-сервера требуется только тогда, когда его конфигурационный файл был изменён.
Обработчик объявляется в секции handlers и вызывается из задачи с помощью директивы notify:
tasks:
- name: Обновление конфигурации Nginx
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
notify: Перезапуск Nginx
handlers:
- name: Перезапуск Nginx
service:
name: nginx
state: reloaded
Важно: имя в notify должно точно совпадать с именем обработчика. Ansible собирает все вызовы обработчиков за время выполнения плейбука и запускает их в конце каждого play, даже если обработчик был вызван несколько раз — он выполнится только один раз. Это предотвращает избыточные перезапуски служб и повышает эффективность.
Переменные и приоритеты
Ansible предоставляет множество способов определения переменных, что даёт гибкость, но требует понимания порядка их применения. Переменные могут поступать из:
- Файлов
group_vars/иhost_vars/— автоматически загружаются при совпадении имени группы или хоста. - Секции
varsв плейбуке — локальные переменные для конкретного play. - Файлов, подключённых через
vars_files— удобно для вынесения конфигураций в отдельные документы. - Ролей:
defaults/(низкий приоритет) иvars/(высокий приоритет). - Командной строки через флаг
-e— самый высокий приоритет, используется для быстрого переопределения.
Пример:
# group_vars/webservers.yml
nginx_port: 8080
document_root: /var/www/html
# playbook.yml
- hosts: webservers
vars:
server_name: example.com
tasks:
- name: Развертывание шаблона
template:
src: site.conf.j2
dest: /etc/nginx/sites-available/default
В шаблоне site.conf.j2 можно использовать все три переменные: две из group_vars и одну из vars.
Ansible также автоматически собирает факты — информацию о системе: операционная система, IP-адреса, объём памяти, количество ядер и многое другое. Эти факты доступны как переменные (ansible_os_family, ansible_default_ipv4.address) и позволяют писать адаптивные плейбуки, работающие на разных платформах.
Факты и адаптивная автоматизация
Факты (facts) — это данные, собранные Ansible с управляемых узлов перед выполнением задач. Они позволяют принимать решения на основе реального состояния системы. Например:
- name: Установка пакетного менеджера
apt:
name: nginx
state: present
when: ansible_os_family == "Debian"
- name: Установка пакетного менеджера
yum:
name: nginx
state: present
when: ansible_os_family == "RedHat"
Этот подход обеспечивает кроссплатформенность без дублирования логики. Сбор фактов можно отключить (gather_facts: no), если они не нужны, чтобы ускорить выполнение.
Лучшие практики
- Идемпотентность — каждая задача должна быть безопасной для многократного запуска. Ansible гарантирует это через проверку текущего состояния перед изменением.
- Читаемость — используйте осмысленные имена задач, группируйте связанные действия, избегайте «магических» значений.
- Модульность — выносите повторяющуюся логику в роли, а не копируйте блоки кода.
- Безопасность — храните секреты в Vault, не коммитьте пароли в Git.
- Тестирование — используйте
ansible-lintдля проверки стиля,moleculeдля интеграционного тестирования ролей. - Версионирование — весь код Ansible должен находиться под контролем версий, как и любой другой программный проект.
Пример: полный цикл автоматизации в AWS
Представим, что нужно развернуть масштабируемое веб-приложение в облаке AWS. Процесс может включать:
- Подготовка инфраструктуры — создание EC2-инстансов, VPC, security groups через модули
amazon.aws.ec2,amazon.aws.ec2_vpc_netи другие. - Настройка ОС — обновление пакетов, установка зависимостей, настройка времени и локали.
- Развёртывание приложения — копирование артефактов, настройка reverse proxy, запуск службы.
- Мониторинг и логирование — установка агентов CloudWatch или Prometheus.
- Очистка — удаление временных ресурсов после завершения.
Всё это можно описать в одном или нескольких плейбуках, используя динамический инвентарь для автоматического обнаружения новых инстансов. После первого запуска инфраструктура полностью воспроизводима: достаточно выполнить команду ansible-playbook deploy.yml, и система придет в заданное состояние.